package com.pig.easy.bpm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.pig.easy.bpm.constant.BpmConstant;
import com.pig.easy.bpm.dto.request.DeptQueryDTO;
import com.pig.easy.bpm.dto.request.DeptSaveOrUpdateDTO;
import com.pig.easy.bpm.dto.response.DeptDTO;
import com.pig.easy.bpm.dto.response.ItemDTO;
import com.pig.easy.bpm.dto.response.TreeDTO;
import com.pig.easy.bpm.entity.DeptDO;
import com.pig.easy.bpm.entityError.EntityError;
import com.pig.easy.bpm.mapper.DeptMapper;
import com.pig.easy.bpm.service.CompanyService;
import com.pig.easy.bpm.service.DeptService;
import com.pig.easy.bpm.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author pig
 * @since 2020-05-20
 */
@Service
@Slf4j
public class DeptServiceImpl extends BeseServiceImpl<DeptMapper, DeptDO> implements DeptService {

    @Autowired
    DeptMapper deptMapper;
    @Autowired
    CompanyService companyService;

    private static final String DEFAULT_ROOT_DEPT_CODE = "";

    @Override
    public Result<PageInfo<DeptDTO>> getListByCondition(DeptQueryDTO deptQueryDTO) {

        BestBpmAsset.isAssetEmpty(deptQueryDTO);
        BestBpmAsset.isAssetEmpty(deptQueryDTO.getTenantId());
        int pageIndex = CommonUtils.evalInt(deptQueryDTO.getPageIndex(), DEFAULT_PAGE_INDEX);
        int pageSize = CommonUtils.evalInt(deptQueryDTO.getPageSize(), DEFAULT_PAGE_SIZE);

        PageHelper.startPage(pageIndex, pageSize);
        List<DeptDTO> deptDTOS = deptMapper.getListByCondition(deptQueryDTO);
        if (deptDTOS == null) {
            deptDTOS = new ArrayList<>();
        }
        PageInfo<DeptDTO> pageInfo = new PageInfo<>(deptDTOS);

        return Result.responseSuccess(pageInfo);
    }

    @Override
    public Result<List<DeptDTO>> getList(DeptQueryDTO deptQueryDTO) {

        BestBpmAsset.isAssetEmpty(deptQueryDTO);

        if (CommonUtils.evalInt(deptQueryDTO.getPageIndex()) < 0) {
            deptQueryDTO.setPageIndex(DEFAULT_PAGE_INDEX);
        }
        if (CommonUtils.evalInt(deptQueryDTO.getPageSize()) < 0) {
            deptQueryDTO.setPageSize(MAX_PAGE_SIZE);
        }

        Result<PageInfo<DeptDTO>> result = getListByCondition(deptQueryDTO);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }
        List<DeptDTO> list = result.getData().getList();
        if (list == null) {
            list = new ArrayList<>();
        }
        return Result.responseSuccess(list);
    }

    @Override
    public Result<DeptDTO> getDeptByDeptId(Long deptId) {

        BestBpmAsset.isAssetEmpty(deptId);

        DeptDO deptDO = deptMapper.selectById(deptId);
        if (deptDO == null) {
            return Result.responseError(EntityError.DATA_NOT_FOUND_ERROR);
        }
        DeptDTO deptDTO = BeanUtils.switchToDTO(deptDO, DeptDTO.class);
        return Result.responseSuccess(deptDTO);
    }

    @Override
    public Result<DeptDTO> getDeptByDeptCode(String deptCode) {

        BestBpmAsset.isAssetEmpty(deptCode);
        DeptDO deptDO = deptMapper.selectOne(new QueryWrapper<>(DeptDO.builder().deptCode(deptCode).build()));
        if (deptDO == null) {
            return Result.responseError(EntityError.DATA_NOT_FOUND_ERROR);
        }
        DeptDTO deptDTO = BeanUtils.switchToDTO(deptDO, DeptDTO.class);
        return Result.responseSuccess(deptDTO);
    }

    @Override
    public Result<List<ItemDTO>> getDeptItemList(DeptQueryDTO deptQueryDTO) {

        deptQueryDTO.setPageIndex(DEFAULT_PAGE_INDEX);
        deptQueryDTO.setPageSize(MAX_PAGE_SIZE);
        Result<List<DeptDTO>> result = getList(deptQueryDTO);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }
        List<ItemDTO> itemDTOS = new ArrayList<>();
        ItemDTO itemDTO = null;
        for (DeptDTO dept : result.getData()) {
            itemDTO = new ItemDTO(dept.getDeptName(),dept.getDeptCode());
            itemDTOS.add(itemDTO);
        }
        return Result.responseSuccess(itemDTOS);
    }

    @Override
    public Result<List<ItemDTO>> getDeptIdItemList(DeptQueryDTO deptQueryDTO) {

        deptQueryDTO.setPageIndex(DEFAULT_PAGE_INDEX);
        deptQueryDTO.setPageSize(MAX_PAGE_SIZE);
        Result<List<DeptDTO>> result = getList(deptQueryDTO);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }
        List<ItemDTO> itemDTOS = new ArrayList<>();
        ItemDTO itemDTO = null;
        for (DeptDTO dept : result.getData()) {
            itemDTO = new ItemDTO(dept.getDeptName(),dept.getDeptId());
            itemDTOS.add(itemDTO);
        }
        return Result.responseSuccess(itemDTOS);
    }

    @Override
    public Result<List<TreeDTO>> getDeptTree(Long parentDeptId, String tenantId) {

        Result<List<TreeDTO>> result = getDeptTree(parentDeptId, null, tenantId);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }
        return Result.responseSuccess(result.getData());
    }

    @Override
    public Result<List<TreeDTO>> getDeptTree(Long parentDeptId, Long companyId, String tenantId) {

        if(CommonUtils.evalLong(parentDeptId) < 0){
            parentDeptId = 0L;
        }
        if(CommonUtils.evalLong(companyId) < 0){
            companyId = 0L;
        }
        BestBpmAsset.isAssetEmpty(tenantId);
        DeptQueryDTO deptQueryDTO = new DeptQueryDTO();
        deptQueryDTO.setTenantId(tenantId);

        Result<List<DeptDTO>> result = getList(deptQueryDTO);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }

        List<TreeDTO> list = new ArrayList<>();
        TreeDTO treeDTO = null;

        for (DeptDTO deptDTO : result.getData()) {
            if (deptDTO != null) {
                treeDTO = new TreeDTO();
                treeDTO.setId(SnowKeyGenUtils.getInstance().getNextId());
                treeDTO.setTreeId(deptDTO.getDeptId());
                treeDTO.setTreeCode(deptDTO.getDeptCode());
                treeDTO.setTreeName(deptDTO.getDeptName());
                treeDTO.setTempTreeId(deptDTO.getCompanyId());
                treeDTO.setParentId(deptDTO.getDeptParentId());
                treeDTO.setTreeTypeCode("dept");
                treeDTO.setTreeType(2);
                list.add(treeDTO);
            }
        }
        list = makeTree(list,parentDeptId);

        /* 移除非 */
        Iterator<TreeDTO> iterator = list.iterator();
        while (iterator.hasNext()){
            TreeDTO next = iterator.next();
            if(!next.getParentId().equals(parentDeptId)
                    || !companyId.equals(next.getTempTreeId())){
                iterator.remove();
            }
        }

        return Result.responseSuccess(list);
    }

    @Override
    public Result<List<TreeDTO>> getOrganTree(String tenantId, Long parentCompantId) {

        Result<List<TreeDTO>> result = companyService.getCompanyTree(parentCompantId,tenantId);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }
        List<TreeDTO> companyTreeList = result.getData();

        List<TreeDTO> list = new ArrayList<>();
        TreeDTO treeDTO = null;

        for(TreeDTO temp : companyTreeList){
            list.add(makeOrganTree(temp,tenantId,0L,1));
        }

        return Result.responseSuccess(list);
    }

    private TreeDTO makeOrganTree(TreeDTO tree,String tenantId, Long parentId,Integer treeType) {

        List<TreeDTO> tempList = new ArrayList<>();
        if(tree.getChildren() == null){
            tree.setChildren(new ArrayList<>());
        }
        List<TreeDTO> children = tree.getChildren();
        Result<List<TreeDTO>> result = getDeptTree(parentId, tree.getTreeId(), tenantId);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            log.error("makeOrganTree error,message :{}",result.getEntityError());
            return tree;
        }
        tempList.addAll(result.getData());

        for(TreeDTO temp : children){
            if(temp.getTreeType().equals(treeType)) {
                tempList.add(makeOrganTree(temp, tenantId, temp.getTreeId(),treeType));
            }
        }
        tree.setChildren(tempList);
        return tree;
    }

    @Override
    public Result<List<TreeDTO>> getDeptTree(String tenantId) {
        Result<List<TreeDTO>> result = getDeptTree(null, tenantId);
        if (result.getEntityError().getCode() != EntityError.SUCCESS.getCode()) {
            return Result.responseError(result.getEntityError());
        }
        return Result.responseSuccess(result.getData());
    }


    @Override
    public Result<Integer> insertDept(DeptSaveOrUpdateDTO deptSaveOrUpdateDTO) {

        BestBpmAsset.isAssetEmpty(deptSaveOrUpdateDTO);
        BestBpmAsset.isAssetEmpty(deptSaveOrUpdateDTO.getTenantId());
        BestBpmAsset.isAssetEmpty(deptSaveOrUpdateDTO.getDeptCode());

        // 默认 key 格式   租户 +":" + key
        if (!deptSaveOrUpdateDTO.getDeptCode().startsWith((deptSaveOrUpdateDTO.getTenantId()))) {
            deptSaveOrUpdateDTO.setDeptCode(deptSaveOrUpdateDTO.getTenantId()
                    + BpmConstant.COMMON_CODE_SEPARATION_CHARACTER
                    + "dept"
                    + BpmConstant.COMMON_CODE_SEPARATION_CHARACTER
                    + deptSaveOrUpdateDTO.getDeptCode());
        }
        DeptDO dept = BeanUtils.switchToDO(deptSaveOrUpdateDTO, DeptDO.class);
        int num = deptMapper.insert(dept);
        return Result.responseSuccess(num);
    }

    @Override
    public Result<Integer> updateDept(DeptSaveOrUpdateDTO deptSaveOrUpdateDTO) {

        BestBpmAsset.isAssetEmpty(deptSaveOrUpdateDTO);
        BestBpmAsset.isAssetEmpty(deptSaveOrUpdateDTO.getTenantId());
        BestBpmAsset.isAssetEmpty(deptSaveOrUpdateDTO.getDeptCode());

        DeptDO dept = BeanUtils.switchToDO(deptSaveOrUpdateDTO, DeptDO.class);
        int num = deptMapper.update(dept, new QueryWrapper<>(DeptDO.builder().deptCode(deptSaveOrUpdateDTO.getDeptCode()).build()));

        return Result.responseSuccess(num);
    }
}
